package com.zhihu.matisse.loader;

import com.zhihu.matisse.listener.LoaderCallback;
import com.zhihu.matisse.model.Album;
import com.zhihu.matisse.model.Item;
import com.zhihu.matisse.model.SelectionSpec;
import com.zhihu.matisse.utils.L;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.app.Context;
import ohos.data.dataability.DataAbilityPredicates;
import ohos.data.resultset.CombinedResultSet;
import ohos.data.resultset.ResultSet;
import ohos.data.resultset.TableResultSet;
import ohos.media.codec.CodecDescriptionList;
import ohos.media.photokit.metadata.AVStorage;

import java.util.Arrays;
import java.util.List;

public class ResultSetLoader {
    private static final String[] PROJECTION = {
            AVStorage.AVBaseColumns.ID,
            AVStorage.AVBaseColumns.DISPLAY_NAME,
            AVStorage.AVBaseColumns.MIME_TYPE,
            AVStorage.AVBaseColumns.SIZE,
            AVStorage.AVBaseColumns.DATA,
            AVStorage.AVBaseColumns.DURATION,
            AVStorage.AVBaseColumns.DATE_ADDED};
    private static final String SELECTION_29 =
            AVStorage.AVBaseColumns.SIZE + ">?";
    private static final String[] SELECTION_ARGS = new String[]{"1"};


    // ===========================================================

    // === params for album ALL && showSingleMediaType: true ===
    private static final String SELECTION_ALL_FOR_SINGLE_MEDIA_TYPE =
            AVStorage.AVBaseColumns.MIME_TYPE + "=?"
                    + " OR " + AVStorage.AVBaseColumns.MIME_TYPE + "=?"
                    + " OR " + AVStorage.AVBaseColumns.MIME_TYPE + "=?"
                    + " OR " + AVStorage.AVBaseColumns.MIME_TYPE + "=?"
                    + " OR " + AVStorage.AVBaseColumns.MIME_TYPE + "=?"
                    + " OR " + AVStorage.AVBaseColumns.MIME_TYPE + "=?"
                    + " OR " + AVStorage.AVBaseColumns.MIME_TYPE + "=?"
                    + " AND " + AVStorage.AVBaseColumns.SIZE + ">0";

    private static String[] getSelectionArgsForSingleMediaType() {
        return new String[]{"image/jpeg","image/png","image/gif","image/bmp","image/heif","image/heic","image/webp"};
    }
    // =========================================================

    private static final String SELECTION_ALL_FOR_GIF =

            AVStorage.AVBaseColumns.MIME_TYPE + "=?"
                    + " AND " + AVStorage.AVBaseColumns.SIZE + ">0";

    private static String[] getSelectionArgsForGifType() {
        return new String[]{"image/gif"};
    }
    // ===============================================================

    // === params for ordinary album && showSingleMediaType: true  && MineType=="image/gif" ===
    private static final String SELECTION_ALBUM_FOR_GIF =
                    AVStorage.AVBaseColumns.MIME_TYPE + "=?"
                    + " AND " + AVStorage.AVBaseColumns.SIZE + ">0";

    private static String[] getSelectionAlbumArgsForGifType() {
        return new String[]{"image/gif"};
    }
    private Context mContext;
    private ResultSetLoaderTask loaderTask;
    private LoaderCallback<ResultSet> loaderCallback;
    private boolean mCapture = false;


    public void setContext(Context mContext) {
        this.mContext = mContext;
    }

    public Context getContext() {
        return mContext;
    }

    public ResultSetLoader(Context mContext){
        this.mContext = mContext;
        newLoad(false);
    }

    public ResultSetLoader(Context mContext,boolean mCapture){
        this.mContext = mContext;
        newLoad(mCapture);
    }
    private void newLoad(boolean mCapture){
        this.mCapture = mCapture;
        String selection;
        String[] selectionArgs;
        if (SelectionSpec.getInstance().onlyShowGif()) {
            selection = SELECTION_ALL_FOR_GIF;
            selectionArgs = getSelectionArgsForGifType();
        } else if (SelectionSpec.getInstance().onlyShowImages()) {
            selection = SELECTION_ALL_FOR_SINGLE_MEDIA_TYPE;
            selectionArgs =
                    getSelectionArgsForSingleMediaType();
        } else if (SelectionSpec.getInstance().onlyShowVideos()) {
            List<String> mimes = CodecDescriptionList.getSupportedMimes();
            StringBuilder query = new StringBuilder(126);
            selectionArgs = (String[]) mimes.toArray();
            int size = mimes.size();
            for (int i = 0; i <size; i++) {
                if (i != 0){
                    query.append(" OR ");
                }
                query.append(AVStorage.AVBaseColumns.MIME_TYPE);
                query.append("=?");
            }
            query.append(" AND ");
            query.append(AVStorage.AVBaseColumns.SIZE );
            query.append(">0");
            selection = query.toString();
        } else {
            selection = SELECTION_29;
            selectionArgs = SELECTION_ARGS;
        }
        loaderTask = new ResultSetLoaderTask(selection,selectionArgs);
    }

    public void setLoaderCallback(LoaderCallback<ResultSet> loaderCallback) {
        this.loaderCallback = loaderCallback;
    }

    public void load(){
        loaderTask.execute();
    }


    public void cancel(boolean interruptlf){
        if (interruptlf){
            loaderCallback = null;
        }
        loaderTask.cancel(interruptlf);
    }

    class ResultSetLoaderTask extends AsyncTaskLoader<String,ResultSet> {
        private final String selection;
        private final String[] selectionArgs;
        ResultSetLoaderTask(String selection,String[] selectionArgs){
            this.selection = selection;
            this.selectionArgs = selectionArgs;
        }

        @Override
        protected ResultSet doInBackground(String[] strings) {
            ResultSet resultSet;
            DataAbilityHelper helper = DataAbilityHelper.creator(getContext());
            try {

                DataAbilityPredicates predicates = new DataAbilityPredicates(selection);
                predicates.setWhereArgs(Arrays.asList(selectionArgs));
                predicates.orderByDesc(AVStorage.AVBaseColumns.ID);
                resultSet = helper.query(AVStorage.Files.fetchResource("external"),PROJECTION, predicates);
                if (mCapture){
                    TableResultSet dummy = new TableResultSet(PROJECTION);
                    dummy.addRow(new Object[]{Item.ITEM_ID_CAPTURE, Item.ITEM_DISPLAY_NAME_CAPTURE, "image/jpeg", 0,"", 0,0});
                    return new CombinedResultSet(new ResultSet[]{dummy, resultSet});
                }else {
                    return resultSet;
                }
            } catch (DataAbilityRemoteException e) {
                L.d(e.getMessage());
                return null;
            }finally {
                helper.release();
            }
        }

        @Override
        protected void postResult(ResultSet albums) {
            super.postResult(albums);
            if (loaderCallback != null && albums != null){
                loaderCallback.setCallback(albums);
            }
        }
    }
}
